﻿using ServiceStack.Messaging;
using ServiceStack.Redis;
using ServiceStack.Redis.Support;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
/******************************************************************************************************************
 * 
 * 
 * 说　明： Redis发布订阅服务(版本：Version1.0.0)
 * 作　者：李朝强
 * 日　期：2015/05/19
 * 修　改：
 * 参　考：http://my.oschina.net/lichaoqiang/
 * 备　注：暂无...
 * 
 * 
 * ***************************************************************************************************************/
namespace Subscription
{
    [Serializable]
    public class UserInfo
    {
        public int Id;
        public string UserName;
        public int Age;
    }
    class Program
    {



        /// <summary>  
        /// 根据GUID获取16位的唯一字符串  
        /// </summary>  
        /// <param name=\"guid\"></param>  
        /// <returns></returns>  
        public static string GuidTo16String()
        {
            long i = 1;
            foreach (byte b in Guid.NewGuid().ToByteArray())
                i *= ((int)b + 1);
            return string.Format("{0:x}", i - DateTime.Now.Ticks);
        }
        /// <summary>  
        /// 根据GUID获取19位的唯一数字序列  
        /// </summary>  
        /// <returns></returns>  
        public static long GuidToLongID()
        {
            byte[] buffer = Guid.NewGuid().ToByteArray();
            return BitConverter.ToInt64(buffer, 0);
        }

        public static void Test()
        {
            //1.使用Environment.TickCount做为Random参数（即Random的默认参数），重复性最大。

            //2.使用DateTime.Now.Ticks做为Random参数，存在重复。

            //3.使用unchecked((int)DateTime.Now.Ticks)做为Random参数，存在重复。

            //4.使用Guid.NewGuid().GetHashCode()做为random参数，测试不存在重复（或存在性极小）。

            //5.使用RNGCryptoServiceProvider做为random参数，测试不存在重复（或存在性极小）。 
            Random rand = new Random(51);
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine(rand.Next());
            }
        }

        static int GetRandomSeed()
        {
            byte[] bytes = new byte[4];
            System.Security.Cryptography.RNGCryptoServiceProvider rng = new System.Security.Cryptography.RNGCryptoServiceProvider();
            rng.GetBytes(bytes);
            return BitConverter.ToInt32(bytes, 0);
        }



        /// <summary>
        /// 
        /// </summary>
        /// <param name="args"></param>
        static void Main(string[] args)
        {

            for (int i = 0; i < 10000; i++)
            {
                int ads = GetRandomSeed();
                Console.WriteLine(ads);
            }


            Console.ReadLine();

            var a = HttpClientHelper.PostResponse("http://zxxk.com", "a=b&c=d");
            Console.ReadLine();

            //IRedisClient _cli = RedisManager.GetClient();

            //RedisOperator op = new RedisOperator();


            //#region List

            ////string key = "C:txj:001";
            ////op.Remove(key);

            ////将字符串列表添加到redis  
            ////List<string> storeMembers = new List<string>() { "韩梅梅", "李雷", "露西" };
            ////storeMembers.ForEach(x => op.AddItemToList(key, x));


            ////得到指定的key所对应的value集合  
            ////Console.WriteLine("得到指定的key所对应的value集合：");
            ////var members = op.GetAllItemsFromList(key);
            ////members.ForEach(s => Console.WriteLine("additemtolist :" + s));

            ////获取指定索引值List<string>
            ////var item = op.GetItemFromList(key, 2); 
            //#endregion


            //#region Hash

            //string key2 = "C:txj:005";
            ////将数据存入Hash表中  
            ////Console.WriteLine("Hash表数据存储:");
            //UserInfo userInfos = new UserInfo()
            //{
            //    UserName = "李雷2",
            //    Age = 80
            //};
            ////var ser = new ObjectSerializer();
            ////bool results = op.Set<byte[]>(key2, "userInfos", ser.Serialize(userInfos));
            ////op.SetExpire(key2, DateTime.Now.AddMinutes(5));
            ////byte[] infos = op.Get<byte[]>(key2, "userInfos");
            ////userInfos = ser.Deserialize(infos) as UserInfo;
            ////Console.WriteLine("name=" + userInfos.UserName + "   age=" + userInfos.Age);

            ////Console.WriteLine("");


            //string key6 = "C:txj:006";
            //op.SetEntryInHash(key6, "userInfos.UserName", userInfos.UserName);
            ////op.SetEntryInHash(key6, "userInfos.Age", userInfos.Age.ToString());

            //Dictionary<string, string> dic = op.GetAllEntriesFromHash(key6);
            //#endregion



            Console.Title = "订阅服务";

            //发布服务
            //Pub();
            //Console.ReadLine();


            //订阅
            Subscription();

            //RedisClient client = new RedisClient("10.1.1.30", 6379);
            //while (true)
            //{
            //    string input = Console.ReadLine();
            //    client.PublishMessage("channel-1", input);
            //}
        }

        #region 发布/订阅·
        /// 发布
        /// </summary>
        public static void Pub()
        {
            //PooledRedisClientManager
            ServiceStack.Redis.IRedisClientsManager RedisClientManager = new ServiceStack.Redis.PooledRedisClientManager("10.1.1.30:6379");

            //发布、订阅服务 IRedisPubSubServer
            ServiceStack.Redis.RedisPubSubServer pubSubServer = new ServiceStack.Redis.RedisPubSubServer(RedisClientManager, "channel-1", "channel-2");

            //接收消息
            pubSubServer.OnMessage = (channel, msg) =>
            {
                Console.WriteLine(string.Format("服务端:频道{0}接收消息：{1}    时间：{2}", channel, msg, DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")));
                Console.WriteLine("___________________________________________________________________");
            };
            pubSubServer.OnStart = () =>
            {
                Console.WriteLine("发布服务已启动");
                Console.WriteLine("___________________________________________________________________");
            };
            pubSubServer.OnStop = () => { Console.WriteLine("服务停止"); };
            pubSubServer.OnUnSubscribe = (channel) => { Console.WriteLine(channel); };
            pubSubServer.OnError = (e) => { Console.WriteLine(e.Message); };
            pubSubServer.OnFailover = (s) => { Console.WriteLine(s); };

            //pubSubServer.OnHeartbeatReceived = () => { Console.WriteLine("OnHeartbeatReceived"); };
            //pubSubServer.OnHeartbeatSent = () => { Console.WriteLine("OnHeartbeatSent"); };
            //pubSubServer.IsSentinelSubscription = true;
            pubSubServer.Start();


        }


        /// <summary>
        /// 发送消息
        /// </summary>
        public static Task Send()
        {
            return Task.Run(() =>
            {
                RedisClient client = new RedisClient("10.1.1.30", 6379);
                client.PublishMessage("channel-1", "这是我发送的消息！");
            });
        }

        /// <summary>
        /// 订阅
        /// </summary>
        public static void Subscription()
        {
            using (RedisClient consumer = new RedisClient("10.1.1.30", 6379))
            {
                //创建订阅
                IRedisSubscription subscription = consumer.CreateSubscription();

                //接收消息处理
                subscription.OnMessage = (channel, msg) =>
                {
                    if (!msg.Equals("CTRL:PULSE"))
                    {
                        Console.WriteLine("频道【" + channel + "】订阅客户端接收消息：" + ":" + msg + "         [" + DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss") + "]" + "      订阅数：" + subscription.SubscriptionCount);
                        //Console.WriteLine("订阅数：" + subscription.SubscriptionCount);
                        //Console.WriteLine("___________________________________________________________________");
                    }
                };

                //订阅事件处理
                subscription.OnSubscribe = (channel) =>
                {
                    Console.WriteLine("订阅客户端：开始订阅" + channel);
                };

                //取消订阅事件处理
                subscription.OnUnSubscribe = (a) => { Console.WriteLine("订阅客户端：取消订阅"); };

                //模拟：发送100条消息给服务
                //Task.Run(() =>
                //{
                //    using (ServiceStack.Redis.IRedisClient publisher = new ServiceStack.Redis.RedisClient("10.1.1.30", 6379))
                //    {
                //        for (int i = 1; i <= 10; i++)
                //        {
                //            publisher.PublishMessage("channel-1", string.Format("这是我发送的第{0}消息!", i));
                //            System.Threading.Thread.Sleep(200);
                //        }
                //    }
                //    subscription.UnSubscribeFromAllChannels();
                //});

                //订阅频道
                subscription.SubscribeToChannels("__keyspace@0__:C:0:0:0:28719920", "channel-1", "channel-2", "__keyspace@0__:tangxiaojun", "__keyevent@0__:del");
            }

        }


        #endregion

        /// <summary>
        /// Example
        /// </summary>
        public static void Example()
        {
            var messagesReceived = 0;
            var PublishMessageCount = 10;
            string MessagePrefix = "LCQ:", ChannelName = "channel-4";
            using (var redisConsumer = new RedisClient("10.1.1.30", 6379))
            using (var subscription = redisConsumer.CreateSubscription())
            {
                //订阅
                subscription.OnSubscribe = channel =>
                {
                    Console.WriteLine("订阅频道'{0}'", channel);
                    Console.WriteLine();
                };
                //取消订阅
                subscription.OnUnSubscribe = channel =>
                {
                    Console.WriteLine("取消订阅 '{0}'", channel);
                    Console.WriteLine();
                };

                //接收消息
                subscription.OnMessage = (channel, msg) =>
                {
                    Console.WriteLine("接收消息 '{0}' from channel '{1}'", msg, channel);
                    Console.WriteLine();
                    //As soon as we've received all 5 messages, disconnect by unsubscribing to all channels
                    if (++messagesReceived == PublishMessageCount)
                    {
                        subscription.UnSubscribeFromAllChannels();
                    }
                };

                ThreadPool.QueueUserWorkItem(x =>
                {
                    Thread.Sleep(200);
                    Console.WriteLine("开始发送消息...");

                    using (var redisPublisher = new RedisClient("10.1.1.30", 6379))
                    {
                        for (var i = 1; i <= PublishMessageCount; i++)
                        {
                            var message = MessagePrefix + i;
                            Console.WriteLine("正在发布消息 '{0}' 到频道 '{1}'", message, ChannelName);
                            Console.WriteLine();
                            redisPublisher.PublishMessage(ChannelName, message);
                        }
                    }
                });

                Console.WriteLine("开始启动监听 '{0}'", ChannelName);
                subscription.SubscribeToChannels(ChannelName); //blocking
            }

            Console.WriteLine("EOF");
        }
    }
}